package org.zkoss.zk.ui;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.ceva.training.persistence.bo.Course;
import org.ceva.training.persistence.bo.CourseDocument;
import org.ceva.training.persistence.dao.CourseDAO;
import org.springframework.context.ApplicationContext;
import org.ceva.training.service.CourseModel;
import org.ceva.training.util.constants.Constant;
import org.zkoss.lang.Strings;

import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.KeyEvent;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.FieldComparator;
import org.zkoss.zul.Fileupload;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listheader;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

import org.zkoss.zkplus.databind.BindingListModelList;
import org.zkoss.zkplus.databind.DataBinder;
import org.zkoss.zkplus.spring.SpringUtil;

public class CourseWindow  extends GenericForwardComposer {
	//ZK databinder
	protected DataBinder binder;

	//Course Model
	@Resource
	protected CourseModel courseModel = null;
	
	//main control window
	@Resource
	protected Window CourseWnd; //main window
	@Resource
	protected Listbox courseList; //domain object summary list
	
	@Resource
	protected Listbox courseDocList; //domain object summary list
	
	@Resource
	protected Component courseDetail; //domain object detail
	
	//edit mode
	@Resource
	protected Component courseEdit; //edit panel
	@Resource
	protected Textbox firstname;
//	@Resource
//	protected Datebox date;
//	@Resource
//	protected Spinner priority;
	
	//buttons
	@Resource
	protected Button courseCreate; //new button
	@Resource
	protected Button courseUpdate; //edit button
	@Resource
	protected Button courseDelete; //delete button
	@Resource
	protected Button courseSave; //save button
	@Resource
	protected Button courseCancel; //cancel button

	//operation transient state
	protected Course _tmpSelected; //store original selected entity
	protected boolean _create; //when new a entity
	protected boolean _editMode; //switch to edit mode when doing editing(new/update)
	protected int _lastSelectedIndex = -1; //last selectedIndex before delete
	
	
	
	public CourseModel getCourseModel() {
		return courseModel;
	}

	public void setModel(CourseModel CourseModel) {
		this.courseModel = CourseModel;
	}
	
	public void refreshModel() {
		binder.loadAttribute(courseList, "model"); //reload model to force refresh
	}

	//-- view/edit mode --//
	public void setEditMode(boolean b) {
		_editMode = b;
		switchMode();
	}
	
	public boolean isViewMode() {
		return !_editMode;
	}
	public boolean getViewMode() {
		return !_editMode;
	}
	
	public boolean isEditMode() {
		return _editMode; 
	}

	public boolean isCreate() {
		return _create;
	}
	
	public boolean isNotSelected() {
		return this.courseModel.getSelected() == null;
	}

	private void switchMode() {
		binder.loadComponent(courseDetail); //reload visible to force refresh
		setFocus();
	}
	
	private void setFocus() {
		if (_editMode) {
			firstname.focus();
		} else {
			if (((List)courseList.getModel()).isEmpty()) {
				//no result in list, focus on new button
				courseCreate.focus();
			} else {
				if (_create) {
					courseCreate.focus();
				} else {
					courseList.focus();
				}
			}
		}
	}
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		
		ApplicationContext ctx = SpringUtil.getApplicationContext();
		CourseDAO courseDAO = (CourseDAO) ctx.getBean("CourseDAO");	
		courseModel = new CourseModel();
		courseModel.setDAO(courseDAO);
		courseModel.setMaxResults(25);
		List model = (List)courseDAO.findAll();
		
		if (!model.isEmpty()) {		
			BindingListModelList bindmodel = new BindingListModelList(model,true);						
			courseModel.setSelected((Course)bindmodel.get(0));
			//courseList.setModel(bindmodel);		
		}
		
		//setFocus();
	}
	//-- Initialization --//
//	@On("CourseWin.onCreate")
	public void onWinCreate() {
		
		
		ApplicationContext ctx = SpringUtil.getApplicationContext();
		CourseDAO courseDAO = (CourseDAO) ctx.getBean("CourseDAO");	
		courseModel = new CourseModel();
		courseModel.setDAO(courseDAO);
		courseModel.setMaxResults(25);
		List model = (List)courseDAO.findAll();
		
		if (!model.isEmpty()) {		
			BindingListModelList bindmodel = new BindingListModelList(model,true);
			//courseModel.setSelected((Course)bindmodel.get(0));
			courseList.setModel(bindmodel);
		}
		
		setFocus();
	}
	
	//-- view mode control --//
//	@On("CourseWnd.onCtrlKey")
	public void onCtrlKey(Event event) {
		final List items = courseList.getItems(); 
		if (!items.isEmpty() && (!_editMode || !_create)) {
			final int keycode = ((KeyEvent) event).getKeyCode();
			if (keycode == KeyEvent.DOWN || keycode == KeyEvent.UP){
				//handle no selected item case
				if (courseList.getSelectedIndex() < 0) { //no selected item
					//try our best to guess one
					if (_lastSelectedIndex >= 0) {
						final int index = Math.min(items.size() - 1, _lastSelectedIndex);
						courseList.setSelectedIndex(index);
						Events.sendEvent(new SelectEvent("onSelect", courseList, courseList.getSelectedItems()));
					}
				}
				courseList.focus();
			}
		}
	}
	
//@On("courseList.onSelect")
	public void onSelect(Event event) {
		final int index = courseList.getSelectedIndex();
		if (index >= 0) {
			_lastSelectedIndex = index;
			_create = false;
		}
	}
	
//	@On("courseCreate.onClick")
	public void onCourseCreate(Event event) {
		if (getViewMode()) {
			//prepare a new Course
			_tmpSelected = courseModel.getSelected();
			_create = true;
			courseModel.setSelected(new Course());
			
			//switch to edit mode
			setEditMode(true);
		}
	}
	
//	@On("courseUpdate.onClick")
	public void onUpdate(Event event) {
		if (getViewMode()) {
			if (courseModel.getSelected() != null) {
				_create = false;

				//switch to edit mode
				setEditMode(true);
			}
		}
	}
	
//	@On("courseDelete.onClick")
	public void onDelete(Event event) {
		if (getViewMode()) {
			if (courseModel.getSelected() != null) {
				_create = false;
				newConfirmDelete().show();
			}
		}
	}
	

//	@On("courseUpdate.onClick")
	public void onDocOpen(Event event) {
		
	}

	public void onDocDelete(Event event) {
		//courseDocList.getSelectedItem().getFellow("");
	}
	public void onDocUploadClick(Event event) {
		try{
			
			org.zkoss.util.media.Media[] media = Fileupload.get(-1);
			Set<CourseDocument> courseDocuments = new HashSet<CourseDocument>();
			if (media != null) {
				for (int i = 0; i < media.length; i++) {
					  InputStream in = media[i].getStreamData();
					  
					  	 File outfile=new File(Constant.UPLOADED_FILE_DIR+media[i].getName());
					  	 System.out.println(Constant.UPLOADED_FILE_DIR+media[i].getName());
					  	 outfile.createNewFile();
					     OutputStream out = new FileOutputStream(outfile); 
					     // Transfer bytes from in to out
					     byte[] buf = new byte[1024];
					     int len;
					     while ((len = in.read(buf)) > 0) {
					        out.write(buf, 0, len);
					      }
					     in.close();
					     out.close();
					     CourseDocument coursedoc = new CourseDocument();
					     coursedoc.setDocumentname(media[i].getName());
					     coursedoc.setCourse(courseModel.getSelected());
					     courseDocuments.add(coursedoc);
				}
				if(courseModel.getSelected().getCourseDocuments() != null)
					courseModel.getSelected().getCourseDocuments().addAll(courseDocuments);
				else
					courseModel.getSelected().setCourseDocuments(courseDocuments);
				
				this.courseModel.merge();	
				//refresh the courseList
				refreshModel();
				//switch to view mode
				setEditMode(false);
			}
		}catch (Exception e) {
			try{
			Messagebox.show("There was some error uploading file ... try again", "Error", Messagebox.OK, Messagebox.ERROR);
			}catch (InterruptedException ex){
				ex.printStackTrace();
			}
			e.printStackTrace();
		}
	}
			
	
	
	//-- sorting --//
//	@On("courseFirstNameSort.onSort,courseLastNameSort.onSort,courseRoleSort.onSort")
	public void onSort(Event event) {
		final Listheader lh = (Listheader) event.getTarget();
		final String sortDirection = lh.getSortDirection(); //original direction
		if ("ascending".equals(sortDirection)) {
			final Comparator cmpr = lh.getSortDescending();
			if (cmpr instanceof FieldComparator) {
				final String orderBy = ((FieldComparator)cmpr).getOrderBy();
				courseModel.setOrderBy(orderBy); //update query string
			}
		} else if ("descending".equals(sortDirection) || "natural".equals(sortDirection) || Strings.isBlank(sortDirection)) {
			final Comparator cmpr = lh.getSortAscending();
			if (cmpr instanceof FieldComparator) {
				final String orderBy = ((FieldComparator)cmpr).getOrderBy();
				courseModel.setOrderBy(orderBy); //update query string
			}
		}
	}
	
	//-- edit mode control --//
//	@On("courseSave.onClick,CourseWin.onOK")
	public void onSave(Event event) {
		if (isEditMode()) {
			//validate
			validate();

			//save into bean
			binder.saveComponent(courseEdit); //reload model to force refresh
			
			//store into db
			if (_create) {
				this.courseModel.persist();
			} else {
				try {
					this.courseModel.merge();
				} catch (Exception e1) {
					try {
						Messagebox.show(getUpdateDeletedMessage());
					} catch (InterruptedException e2) {
						//ignore
					}
				}
			}
			//refresh the courseList
			refreshModel();
			//switch to view mode
			setEditMode(false);
		}
	}

//	@On("courseCancel.onClick,CourseWin.onCancel")
	public void onCancel(Event event) {
		if (isEditMode()) {
			//restore to original selected Course if cancel from new
			if (_create) {
				courseModel.setSelected(_tmpSelected);
				_tmpSelected = null;
			}
			
			//switch to view mode
			setEditMode(false);
		}
	}
	
	//--To be override--// 
	/** Validate the input field */
	protected void validate() {
		//date.getValue();
		//priority.getValue();
		firstname.getValue();
	}
	
	/** The info message when end course trying to update a "deleted" entity. */
	protected String getUpdateDeletedMessage() {
		return "Cannot find the selected item, might have been deleted by others.";
	}
	
	/** Get a instance of ConfirmDelete class */
	protected ConfirmDelete newConfirmDelete() {
		return new ConfirmDelete();
	}
	
	/** Delete Confirmation */
	protected class ConfirmDelete {
		/** Show the ConfirmDelete Messagebox */
		public void show() {
			try {
				Messagebox.show(getMessage(),
				        getTitle(),
				        Messagebox.YES+Messagebox.NO,
				        Messagebox.EXCLAMATION,
				        new org.zkoss.zk.ui.event.EventListener() {
							public void onEvent(Event event) {
								if ("onYes".equals(event.getName())) {
									doYes();
								}
							}
						}
					);
			} catch (InterruptedException ex) {
				//ignore
			}
		}
		
		/** Operation when end course click Yes button in confirm delete Messagebox*/
		public void doYes() {
			try {
				courseModel.delete();
				courseCreate.focus();		
			} catch (Exception e) { 
				//ignore, already deleted by others
			}
			courseModel.setSelected(null);
			//refresh the courseList
			refreshModel();
			//update the courseDetail
			switchMode();
		}
		
		/** Returns title of confirm deleting Messagebox */
		public String getTitle() {
			return "Are you sure?";
		}

		/** Returns message for confirm deleting Messagbox */
		public String getMessage() {
			return "Are you sure you want to delete the selected item?"; 
		}
	}
}
